#include "Block.h"
#include <assert.h>
#include <algorithm>
#include <bitset>

namespace ATSudokuEngine
{

UInt32 Block::Add(const Cell* pCell)
{
	assert(pCell);
	assert(Size() < MAX_CELLS);
	if(MAX_CELLS <= Size())
		return 0;	// error
	
	// Can't add duplicated Cell index
	if(Find(*pCell)!=Null)
	{
		return Size();
	}

	vCells_.push_back(pCell);

	return Size();
}

Bool Block::Set(UInt32 nIndex, UInt32 nValue)
{
	assert(nIndex < Size());
	assert(nValue <= Size());
	if(Size() <= nIndex)
		return False;
	if(Size() < nValue)
		return False;

	if(IsExist(nValue))
		return False;

	const Cell* pOrg = vCells_[nIndex];
	// Should exchange Cell's value
	UInt32 nOrg = pOrg->Value(nValue);
	if(False == IsValid())
	{
		pOrg->Value(nOrg);
		return False;
	}

	return True;
}

void Block::Clear()
{
	vCells_.clear();
}

const Cell* Block::At(UInt32 nIndex) const
{
	assert(nIndex < Size());

	return vCells_.at(nIndex);
}

Bool Block::Clone(UInt32 nIndex, Cell& aCell) const
{
	assert(nIndex < Size());

	aCell.Value(INVALID_VALUE);
	if(Size() <= nIndex)
		return False;
	
	const Cell* pOrg = vCells_.at(nIndex);
	assert(pOrg);
	aCell.Value(pOrg->Value());

	return True;
}

UInt32 Block::Size() const
{
	return (UInt32) vCells_.size();
}

UInt32 Block::Length() const
{
	return Size();
}

const Cell* Block::Find(UInt32 nCellIndex)
{
	Cell aTemp(nCellIndex);
	//CellConstIterator it = std::find(vCells_.begin(), vCells_.end(), &aTemp);
	
	CellIterator itStart = vCells_.begin();
	CellIterator itEnd = vCells_.end();

	for(; itStart!=itEnd; ++itStart)
	{
		if((*itStart)->Index() == nCellIndex)
			return *itStart;
	}

	return Null;
}

Bool Block::IsExist(UInt32 nValue) const
{
	CellConstIterator itStart = vCells_.begin();
	CellConstIterator itEnd = vCells_.end();

	for(; itStart!=itEnd; ++itStart)
	{
		if((*itStart)->Value() == INVALID_VALUE)
			continue;

		if((*itStart)->Value() == nValue)
			return True;
	}

	return False;
}

Bool Block::IsValid() const
{
	assert(Size()<=MAX_BLOCK_CELLS);

	std::bitset<MAX_BLOCK_CELLS> aDuplicatedIndexes;
	
	CellConstIterator itStart = vCells_.begin();
	CellConstIterator itEnd = vCells_.end();

	for(; itStart!=itEnd; ++itStart)
	{
		if((*itStart)->Value() == INVALID_VALUE)
			continue;

		if(false == aDuplicatedIndexes.test((*itStart)->Value()))
			aDuplicatedIndexes.set((*itStart)->Value());
		else
			return False;
	}
	return True;
}

CellConstIterator Block::BeginCells() const
{
	return vCells_.begin();
}

CellConstIterator Block::EndCells() const
{
	return vCells_.end();
}

}	// namespace ATSudokuEngine